package edu.hawaii.senin.iclouds.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Observable;

import javax.swing.JFileChooser;

import edu.hawaii.senin.iclouds.simple.Cloud;
import edu.hawaii.senin.iclouds.simple.ReadConfigException;
import edu.hawaii.senin.iclouds.util.TraffoFilter;
import edu.hawaii.senin.iclouds.view.View;

/**
 * Provides Controller component for traffometer MVC model.
 * 
 * @author Pavel Senin.
 * 
 */
public class Controller extends Observable {

  /**
   * View that presents work for users.
   */
  private View view;

  /**
   * Cloud that does all simulation.
   */
  private Cloud model;

  public boolean stopSimulation;

  /**
   * Instantiates controller.
   * 
   * @param model model to use.
   * @param view view implementation to use.
   */
  public Controller(Cloud model, View view) {

    // this.scheduler = new Scheduler();
    // new Thread(this.scheduler).start();
    // this.scheduler.addObserver(view);

    this.model = model;
    this.view = view;

    model.addObserver(view);
    this.addObserver(model);

    view.addLoadListener(new ConfigLoadListener());
    view.addLogListener(new LogListener());
    view.addRunListener(new RunListener());
    view.addStopListener(new StopListener());    
    view.showGUI();
  }

  /**
   * Loads xml configuration by providing friendly File chooser.
   * 
   * @author Pavel Senin.
   * 
   */
  private class ConfigLoadListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {

      JFileChooser fc = new JFileChooser(System.getProperty("user.dir") + "/config");

      fc.addChoosableFileFilter(new TraffoFilter());
      fc.setAcceptAllFileFilterUsed(false);

      int returnVal = fc.showDialog(view.getJFrame(), "Attach");
      // Process the results.
      if (returnVal == JFileChooser.APPROVE_OPTION) {
        view.addToLog("controller : attaching file: " + fc.getSelectedFile() + ".\n");
        try {
          model.loadConfig(fc.getSelectedFile().getAbsolutePath());
          view.setConfigName(fc.getSelectedFile().getAbsolutePath());
        }
        catch (ReadConfigException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
        }
      }
      else {
        assert true;
        view.addToLog("controller : attachment canceled by user.\n");
      }
      fc.setSelectedFile(null);
    }
  }

  private class LogListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {

      JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
      int returnVal = fc.showSaveDialog(view.getJFrame());
      if (returnVal == JFileChooser.APPROVE_OPTION) {
        File file = fc.getSelectedFile();
        if (file != null) { // if user did not cancel file dialog
          try {
            view.addToLog("controller : setting log file: " + fc.getSelectedFile() + ".\n");
            model.setLogFile(file);
            view.setLogName(fc.getSelectedFile().getAbsolutePath());
          }
          catch (IOException e1) {
            view.addToLog("controller : couldn't get through while selecting log as "
                + fc.getSelectedFile());
            e1.printStackTrace();
          }

        }

      }
    }
  }

  /**
   * Provides listener for Run simulation button.
   * 
   * @author Pavel Senin.
   * 
   */
  private class RunListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
      view.addToLog("controller: Running simulation at " + Calendar.getInstance().getTime());
      model.setPhysicalParameters(view.getPhysicalParameters());
      if (model.modelReady()) {
        stopSimulation = false;
        new Thread(model).start();
      }
      else {
        view.addToLog("Load config first!");
      }
    }
  }
  
  /**
   * Provides listener for the Stop simulation button.
   * 
   * @author Pavel Senin.
   * 
   */
  private class StopListener implements ActionListener {
    /**
     * Contains the action performed event.
     * 
     * @param e the action event.
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
      view.addToLog("controller: Stopping simulation at " + Calendar.getInstance().getTime());
      stopSimulation = true;
      setChanged();
      notifyObservers(stopSimulation);
    }
  }
  
  //
  // /**
  // * Provides listener for Demo button.
  // *
  // * @author Pavel Senin.
  // *
  // */
  // private class SubmitDemoListener implements ActionListener {
  // /**
  // * Contains the action performed event.
  // *
  // * @param e the action event.
  // * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  // */
  // public void actionPerformed(ActionEvent e) {
  // if (model.modelReady()) {
  // view.addToLog("Controller: Submit static data button pressed\n");
  // String host = view.getHostName();
  // String port = view.getPortName();
  // // view.addToLog("Controller: Setting base at " + host + ", port " + port);
  // model.setBase(host, Integer.valueOf(port));
  // model.setPackets(model.getTimedPackets(10));
  // try {
  // model.startApp();
  // }
  // catch (Exception ex) {
  // view.addToLog("Exception! See the log");
  // assert true;
  // }
  // }
  // else {
  // view.addToLog("Load config first!");
  // }
  // }
  // }
  //
  // /**
  // * Provides a listener for real events.
  // *
  // * @author Pavel Senin
  // * @author Robert Puckett
  // *
  // */
  // private class RunRealListener implements ActionListener {
  // /**
  // * Contains the action performed event.
  // *
  // * @param e the action event.
  // * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  // */
  // public void actionPerformed(ActionEvent e) {
  // view.addToLog("Real time simulation button pressed.\n");
  // if (model.modelReady()) {
  //
  // String host = view.getHostName();
  // String port = view.getPortName();
  //
  // model.setBase(host, Integer.valueOf(port));
  // // need to implement connection with view fields.
  //
  // if (model.parseDynamicData(view.getDynamicParameters())) {
  // model.setPackets(model.runTimedDynamicSimulation());
  // try {
  // model.startApp();
  // }
  // catch (Exception ex) {
  // view.addToLog("Exception! See the log");
  // assert true;
  // }
  // // scheduler.queue(model.runTimedDynamicSimulation());
  // }
  // else {
  // view.addToLog("Load config first!");
  // }
  // }
  // else {
  // view.addToLog("Invalid dynamic parameters specified!");
  // }
  // }
  // }
  //
  // /**
  // * Provides a listener for load events.
  // *
  // * @author Pavel Senin
  // * @author Robert Puckett
  // *
  // */
  // private class RunLoadTestListener implements ActionListener {
  // /**
  // * Contains the action performed event.
  // *
  // * @param e the action event.
  // * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  // */
  // public void actionPerformed(ActionEvent e) {
  // // model - go ahead
  // view.addToLog("Load test button pressed\n");
  // // new Thread(model).start();
  // }
  // }
  //
  // /**
  // * Provides a listener for transfer points.
  // *
  // * @author Pavel Senin
  // *
  // */
  // private class TransferPointsListener implements ActionListener {
  // /**
  // * Contains the action performed event.
  // *
  // * @param e the action event.
  // * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  // */
  // public void actionPerformed(ActionEvent e) {
  // view.addToLog("Transfer Points Button pressed, transferring\n");
  // if (model.StaticDataIsLoaded()) {
  // model.convert2Dynamic();
  // }
  // else {
  // view.addToLog("Provide static data first!\n");
  // }
  // }
  // }
  //
  // /**
  // * Provides a listener for stop events.
  // *
  // * @author Pavel Senin
  // * @author Robert Puckett
  // *
  // */
  // private class StopSimulationListener implements ActionListener {
  // /**
  // * Contains the action performed event.
  // *
  // * @param e the action event.
  // * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  // */
  // public void actionPerformed(ActionEvent e) {
  // view.addToLog("STOP the simulation.\n");
  // model.exitApp();
  // }
  // }

}
